package com.scrm.exam.response;


import com.scrm.exam.errorcode.ErrorCode;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.lang.reflect.Array;

/**
 * @param
 */
@Data
@NoArgsConstructor
public class Result<T> implements Serializable {  //<T>泛型

    private static final long serialVersionUID = 8152838058593094046L;

    /**
     * 返回代码
     */
    private Integer code;
    /**
     * 返回消息
     */
    private String msg;

    /**
     * 返回数据
     */
    private T data;

    public Result(T data) {
        this.data = data;
        this.code = ErrorCode.SUCCESS.getCode();
        this.msg = ErrorCode.SUCCESS.getMessage();
    }

    public Result(Integer errorCode, String errorMsg) {
        this.code = errorCode;
        this.msg = errorMsg;
    }

    /**
     * @param errorCode 返回代码
     * @param errorMsg  返回消息
     * @param data      返回数据
     */
    public Result(Integer errorCode, String errorMsg, T data) {

        this.code = errorCode;
        this.msg = errorMsg;
        this.data = data;
    }

    /**
     * 结构体检查，现在没有限制Result  属性只接受Key-Value方式的结构体, 其他非结构体类型, 前端不可解析，所以不用检查
     *
     * @param data 数据泛型
     */
    private void checkData(T data) {
        if (data == null)
            throw new IllegalArgumentException("响应数据不能为空");

        if (Iterable.class.isAssignableFrom(data.getClass())         // 不接受列表, 请包装
                || Array.class.isAssignableFrom(data.getClass())     // 不接受数组, 请包装
                || Number.class.isAssignableFrom(data.getClass())    // 不接受数字, 请包装
                || Boolean.class.isAssignableFrom(data.getClass())   // 不接受布尔值, 请包装
                || String.class.isAssignableFrom(data.getClass())    // 不接受字符串, 请包装
                || Character.class.isAssignableFrom(data.getClass()) // 不接受字符, 请包装
        )
            throw new IllegalArgumentException("响应数据只接受Key-Value结构体");
    }

    public  boolean  isSuccess() {
        return HttpStatus.OK.value() == this.code;
    }

    public static Result success() {
        return new Result<>(true);
    }

    public static <T> Result<T> success(T data) {
        return new Result<>(data);
    }

    public static Result error(ErrorCode e) {
        return new Result(e.getCode(), e.getMessage());
    }

    public static Result error(ErrorCode e, String errorMsg) {
        return new Result(e.getCode(), errorMsg);
    }

}
